from flask import g,render_template,redirect,session
from flask import request,Flask,jsonify,current_app

from info.models import User, Category, News
from info.utils.response_code import RET
from . import profile_blue
from info.utils.commons import login_required
from info import db,constants
from info.utils.image_storage import storage

@profile_blue.route('/user_info')
@login_required
def user_info():
    """
    1/查询用户的登录状态g.user
    2/有缓存直接return，没有缓存就登录
    :return: 
    """
    user = g.user
    if not user:
        return redirect('/')
    data = {
        'user_info':user.to_dict()
    }
    return render_template('news/user.html',data=data)



@profile_blue.route('/user_base_info',methods=['GET','POST'])
@login_required
def user_base_info():
    """
    请求方式有GET
    1/查询用户的登录状态g.user
    2/有缓存直接return，没有缓存就登录
    请求方式POST
    1/获取参数form表单获取个性签名,用户昵称,性别
    2/检查参数非空
    3/保存数据到数据库，左边和右上角同时更新
    4/删除缓存，重新存储缓存
    :return:
    """
    #在缓存中查询是否登录
    user = g.user
    #GET请求直接返回查询结果
    if request.method == 'GET':
        data = {
            'user_info':user.to_dict()
        }
        return render_template('news/user_base_info.html', data=data)
    #获取参数
    nick_name = request.json.get('nick_name')
    signature = request.json.get('signature')
    gender = request.json.get('gender')
    #判断非空
    if not all([nick_name,signature,gender]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    if gender not in ['MAN','WOMAN']:
        return jsonify(errno=RET.PARAMERR,errmsg='参数范围错误')
    #保存到数据库
    user.gender = gender
    user.nick_name = nick_name
    user.signature = signature
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存用户数据失败')
    #清除缓存信息，重新缓存
    session['nick_name'] = nick_name
    print(1)
    return jsonify(errno=RET.OK,errmsg='OK')

@profile_blue.route('/pic_info',methods=['GET','POST'])
@login_required
def user_pic_info():
    """
    1/首先获取缓存信息
    2/请求方式如果是get直接返回
    3/请求方式是post，获取参数
    4/检查参数是否为空，是否可读
    5/存储图片到七牛
    6/图片提交到数据库
    7/缓存图片新的信息
    :return:
    """
    user = g.user
    if request.method == 'GET':
        data ={
            'user_info':user.to_dict()
        }
        return render_template('news/user_pic_info.html',data=data)
    # 获取参数,检查非空
    avatar = request.files.get('avatar')
    if not avatar:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 检查文件格式
    try:
        image_avatar = avatar.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='参数格式错误')
    # 存储到七牛
    try:
        image_data = storage(image_avatar)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='上传图片失败')
    # 保存到数据库
    user.avatar_url = image_data
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存用户数据失败')
    # 拼接图片的绝对路径给前端
    avatar_url = constants.QINIU_DOMIN_PREFIX + image_data
    data = {
        'avatar_url':avatar_url
    }
    return jsonify(errno=RET.OK,errmsg='OK',data=data)


@profile_blue.route('/user_collect',methods=['GET'])
@login_required
def user_collect():
    """
    查询是否登录,如果没有登录跳转到登录页面
    如果登录，就查询关注信息然后返回数据到模板
    :return:
    """
    # 查询用户是否登录
    user = g.user
    if not user:
        return redirect('/')
    # 获取参数
    p = request.args.get('p',1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        p = 1
    # 定义容器
    collections = []
    # 默认当前第一页，防止查数据库出错
    current_page = 1
    # 默认一页就一条数据
    total_page = 1
    # 查询数据库
    try:
        paginate = user.collection_news.paginate(p,constants.USER_COLLECTION_MAX_NEWS, False)
        collections = paginate.items # 得到的是新闻对象
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
    # 容器
    collection_dict_li = []
    for news in collections:
        collection_dict_li.append(news.to_basic_dict())

    data = {
        'collection':collection_dict_li,
        'current_page':current_page,
        'total_page':total_page
    }
    return render_template('news/user_collection.html',data=data)


@profile_blue.route('/user_follow',methods=['GET'])
@login_required
def user_follow():
    """
     如果是get请求，通过用户id查询关注作者的信息并返回data
     如果是post请求，获取参数（不关注），检查参数，移除处理
    :return:
    """
    user = g.user
    if not user:
        return redirect('/')

    p = request.args.get('p',1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        p = 1
    follows = []
    current_page = 1
    total_page = 1
    try:
        paginate = user.followed.paginate(p,constants.USER_COLLECTION_MAX_NEWS, False)
        follows = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
    user_follow_list = []

    for follow_user in follows:
        user_follow_list.append(follow_user.to_dict())
    data = {
        'user_follow':user_follow_list,
        'current_page':current_page,
        'total_page':total_page
    }
    return render_template('news/user_follow.html',data=data)


@profile_blue.route('/pass_info',methods=['GET','POST'])
@login_required
def password_info():
    """
    如果是get请求直接返回模板，如果是post请求
    1/获取参数json
    2/检查参数非空，拿旧密码数据哈希算法后和数据库密码验证
    3/提交数据commit
    4/返回修改成功
    :return:
    """
    user = g.user
    if not user:
        return redirect('/')
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')

    old_pswd = request.json.get('old_pswd')
    new_pswd = request.json.get('new_pswd')
    new_pswd1 = request.json.get('new_pswd1')

    if not all([old_pswd,new_pswd,new_pswd1]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')

    if not user.check_password(old_pswd):
        return jsonify(errno=RET.DATAERR,errmsg='旧密码输入错误')

    if new_pswd != new_pswd1:
        return jsonify(errno=RET.NODATA,errmsg='两次密码不一致')

    user.password = new_pswd
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存用户数据失败')
    return jsonify(errno=RET.OK,errmsg='OK')


@profile_blue.route('/news_release',methods=['GET','POST'])
@login_required
def user_news_release():
    """
    用户是否登录，没有登录跳转主页
    请求方式：GET
    查询新闻分类有哪些，列表存储，去掉最新，返回数据
    return模板
    请求方式：POST
    获取参数，检查参数
    业务处理，返回数据
    :return:
    """
    user = g.user
    if not user:
        return redirect('/')

    if request.method == 'GET':
        # 定义列表存储查询新闻分类对象
        categorys = []
        try:
            categorys = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.NODATA,errmsg='查询数据失败')
        # 定义列表 存储每一个新闻分类的to_dict()
        category_list = []
        for category in categorys:
            category_list.append(category.to_dict())
        category_list.pop(0)
        return render_template('news/user_news_release.html',category_list=category_list)
    # 获取参数
    title = request.form.get('title')
    source = "个人发布"
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    index_image_url = request.files.get('index_image_url')
    content = request.form.get('content')
    # 判断非空
    # print(title,category_id,digest,index_image_url,content)
    if not all([title,category_id,digest,index_image_url,content]):
        return jsonify(errno=RET.PARAMERR,errmsg='数据不完整')
        # 转换新闻分类数据类型
    try:
        category_id = int(category_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数类型错误')
    # 读取图片数据
    try:
        image_data = index_image_url.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数格式错误')
    # 上传新闻图片到七牛
    try:
        key = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='上传图片错误')
    # 实例化新闻对象
    news = News()
    news.title = title
    news.digest = digest
    news.source = source
    news.content = content
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + key
    news.category_id = category_id
    news.user_id = g.user.id
    news.status = 1
    # 保存数据库
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存用户数据失败')
    # 返回数据
    return jsonify(errno=RET.OK, errmsg="发布成功，等待审核")



@profile_blue.route('/news_list')
@login_required
def news_list():
    """
    判断用户是否登录，根据用户查询用户发表的新闻，分页形式显示出来
    :return:
    """
    user = g.user
    if not user:
        return redirect('/')
    p = request.args.get('p',1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        p = 1
    news_li = []
    current_page = 1
    total_page = 1
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(p, constants.USER_COLLECTION_MAX_NEWS, False)
        # 获取当前页数据
        news_li = paginate.items
        # 获取当前页
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
    news_dict_li = []
    for news_items in news_li:
        news_dict_li.append(news_items.to_dict())
    data = {
        'news_list':news_dict_li,
        'current_page':current_page,
        'total_page':total_page
    }
    return render_template('news/user_news_list.html',data=data)




"""
新闻项目
项目的功能：提供一些最新的新闻，来源：用户发布新闻，爬取新闻
 用的是flask框架，前端后端不分离
 用到的技术：数据库，log日志，git仓库，项目部署，一些第三方扩展七牛云和云通讯
 用到的模块sqlalchemy,redis,session,csrfprotect，flask_script
项目的具体实现：
 mvt设计模式
 m:models模型类 用户类，用户和粉丝类；用户和新闻收藏类；新闻类，新闻分类；评论和点赞
 v:user/news/admin 用的是蓝图，
 t:news/admin/
 libs:云通讯 工具包
 utils：验证码/七牛/
 logs：log日志
 migrate：迁移
 配置文件
 启动文件
"""






